package com.cn.task.timer;

import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.cn.xc.utils.DateUtil;
import com.cn.xc.utils.ReflectUtil;

/**
 * FUN: 
 *
 * @author sushy
 * @date 2016-3-23 
 */
public abstract class SchedulerTask implements Runnable {

	protected Log logger = LogFactory.getLog(getClass());
	protected Object lock = new Object();

	private int state = VIRGIN;// 状态
	public static final int VIRGIN = 0;// 初始化
	public static final int SCHEDULED = 1;// 调度
	public static final int CANCELLED = 2;// 取消（暂停）
	public static final int RUNNING = 3;// 运行中
	private static final String[] stateStr = new String[] { "初始化", "调度中",
			"已暂停", "运行中" };

	private Class<IScheduleIterator> iteratorClass;// 调度迭代器类型
	private String iteratorParam;// 调度迭代器参数
	private IScheduleIterator iterator;// 调度迭代器
	private TimerTask timerTask;// 当前定时任务
	private Timer timer;// 定时器（每个任务分配一个，预防线程内存问题）

	private Long taskId;// 任务ID
	private String taskName;// 任务名称
	private boolean daemon = true;// 是否daemon线程
	private String lastRunTime;// 上次运行时间
	private String nextRunTime;// 下次运行时间

	public Timer getTimer() {
		return timer;
	}

	public String getTaskName() {
		return taskName;
	}

	public void setTaskName(String taskName) {
		this.taskName = taskName;
	}

	public boolean isDaemon() {
		return daemon;
	}

	public void setDaemon(boolean daemon) {
		this.daemon = daemon;
	}

	public Long getTaskId() {
		return taskId;
	}

	public void setTaskId(Long taskId) {
		this.taskId = taskId;
	}

	public String getIteratorStr() {
		return iterator.toString();
	}

	/**
	 * 创建一个新的调度任务
	 */
	public SchedulerTask() {
	}

	/**
	 * 方式1: spring注入
	 * 
	 * @param iterator
	 */
	public void setIterator(IScheduleIterator iterator) {
		this.iterator = iterator;
		this.iteratorClass = IScheduleIterator.class;
		this.iteratorParam = null;
	}

	/**
	 * 方式2: spring注入
	 * 
	 * @param iteratorClass
	 */
	public void setIteratorClass(Class<IScheduleIterator> iteratorClass) {
		this.iterator = null;
		this.iteratorClass = iteratorClass;
	}

	/**
	 * 方式2: spring注入
	 * 
	 * @param iteratorParam
	 */
	public void setIteratorParam(String iteratorParam) {
		this.iteratorParam = iteratorParam;
	}

	/**
	 * 初始化检查调度迭代器
	 */
	public void initIterator() {
		if (this.iterator == null) {
			this.iterator = (IScheduleIterator) ReflectUtil
					.newInstance(this.iteratorClass);
			this.iterator.init(this.iteratorParam);
		}
	}

	/**
	 * 当前状态值
	 * 
	 * @return
	 */
	public int getState() {
		synchronized (lock) {
			return state;
		}
	}

	/**
	 * 获取当前状态描述
	 * 
	 * @return
	 */
	public String getStateStr() {
		synchronized (lock) {
			if (state < 0 || state > stateStr.length) {
				return "出现异常";
			}
			return stateStr[state];
		}
	}

	/**
	 * 执行调度
	 */
	public abstract void run();

	/**
	 * 首次调度
	 */
	public boolean schedule() {
		synchronized (lock) {
			iterator.init();
			Date time = iterator.next();
			if (time == null) {
				doCancel();
				return false;
			}

			if (state == CANCELLED) {
				state = VIRGIN;// 恢复初始化状态
			}

			if (state != VIRGIN) {
				return false;
			}

			doSchedule(time);
			return true;
		}
	}

	/**
	 * 执行调度
	 * 
	 * @param nexttime
	 */
	private void doSchedule(Date nexttime) {
		timerTask = null;
		try {
			logger.info("doSchedule start!");
			if (timer == null) {
				timer = new Timer("crm-timer-" + taskId + ":" + taskName,
						daemon);
			}
			timerTask = new SchedulerTimerTask(this);
			lastRunTime = nextRunTime;// 记录上次运行时间
			nextRunTime = DateUtil.date2Str(nexttime, "yyyy-MM-dd HH:mm:ss");// 记录下次运行时间
			timer.schedule(timerTask, nexttime);
			state = SCHEDULED;
		} catch (Throwable t) {
			logger.error("doSchedule error!", t);
		} finally {
			logger.info("doSchedule end!");
		}
	}

	/**
	 * 再次调度
	 * 
	 * @return
	 */
	public boolean reschedule() {
		synchronized (lock) {
			if (state == SchedulerTask.CANCELLED) {
				return false;
			}

			Date nextTime = null;
			long curTime = new Date().getTime();
			do {
				// 取下次执行时间，要求比当前时间大，避免执行频率过快
				nextTime = iterator.next();
				if (nextTime == null) {
					// 如果迭代器返回null就结束
					doCancel();
					return false;
				}
			} while (curTime >= nextTime.getTime());

			doSchedule(nextTime);
			return true;
		}
	}

	/**
	 * 调度执行
	 */
	public void runTask() {
		int taskState = SCHEDULED;
		synchronized (lock) {
			if (state == RUNNING || state == CANCELLED) {
				return;
			}
			taskState = state;
			state = RUNNING;
		}

		try {
			logger.info("runTask begin!");
			run();
		} catch (Throwable t) {
			logger.error("runTask error!", t);
		} finally {
			logger.info("runTask end!");
		}

		synchronized (lock) {
			state = taskState;
		}
	}

	/**
	 * 取消任务
	 */
	public boolean cancel() {
		synchronized (lock) {
			return doCancel();
		}
	}

	/**
	 * 取消任务
	 * 
	 * @return
	 */
	private boolean doCancel() {
		if (state != RUNNING) {
			if (timerTask != null) {
				timerTask.cancel();
			}
		}
		boolean result = (state == SCHEDULED);
		if (result) {
			state = CANCELLED;
		}
		return result;
	}

	/**
	 * 调度执行时间
	 */
	public long scheduledExecutionTime() {
		synchronized (lock) {
			return timerTask == null ? 0 : timerTask.scheduledExecutionTime();
		}
	}

	public String getLastRunTime() {
		return lastRunTime;
	}

	public String getNextRunTime() {
		return nextRunTime;
	}


}
